package jforex;

import java.util.*;

import com.dukascopy.api.*;
import com.dukascopy.api.feed.*;

import java.awt.Color;

public class RenkoStrat1 implements IStrategy, IRenkoBarFeedListener {
    @Configurable("Instrument") public Instrument instrument = Instrument.EURJPY;
    
    @Configurable("Renko Size") public int renkoSize = 25;
    
    private IEngine engine;
    private IConsole console;
    private IHistory history;
    private IContext context;
    private IIndicators indicators;
    private IUserInterface userInterface;
    private IOrder order;
    private int counter;
    private int renkoCount;
    
    public void onStart(IContext context) throws JFException {
        this.engine = context.getEngine();
        this.console = context.getConsole();
        this.history = context.getHistory();
        this.context = context;
        this.indicators = context.getIndicators();
        this.userInterface = context.getUserInterface();
        context.subscribeToRenkoBarFeed(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), this);
    }

    public void onAccount(IAccount account) throws JFException {
    }

    public void onMessage(IMessage message) throws JFException {
    }

    public void onStop() throws JFException {
    }
    
    public void onTick(Instrument instrument, ITick tick) throws JFException {
    }
 
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
    }
    
    public void onBar(Instrument instrument, OfferSide offerSide, PriceRange brickSize, IRenkoBar renkoBar1) {
        if (!instrument.equals(this.instrument))
            return;
        try {
            IRenkoBar renkoBar0 = history.getRenkoBar(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 0);
            if (isFirstBarOfWeek(renkoBar0)) {
                return;
            }
            if (isFirstBarOfWeek(renkoBar1)) {
                renkoBar1 = history.getRenkoBars(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 2, renkoBar1.getTime(), 0).get(0);
            }
            if (!isActive(order)) {
                order = null;
            } else {
                if (isRedBar(renkoBar0) != isRedBar(renkoBar1)) {
                    order.close();
                }
                return;
            }
            if (isRedBar(renkoBar0) == isRedBar(renkoBar1)) {
                IEngine.OrderCommand orderCmd = !isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;
                order = engine.submitOrder(getLabel(instrument), instrument, orderCmd, 0.005, 0.0, 0.0);
            }
        } catch (JFException e) {
            log(e.toString());
        }
    }
    
    private boolean isFirstBarOfWeek(IRenkoBar renkoBar) throws JFException {
        IRenkoBar previousBar = history.getRenkoBars(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 2, renkoBar.getTime(), 0).get(0);
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(new Date(renkoBar.getTime()));
        return cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
                    && cal.get(Calendar.HOUR_OF_DAY) == 21
                    && cal.get(Calendar.MINUTE) == 0
                    && renkoBar.getOpen() != previousBar.getClose();
    }
    
    private boolean isRedBar(IRenkoBar renkoBar) {
        return renkoBar.getOpen() > renkoBar.getLow();
    }
    
    private boolean isActive(IOrder order) {
        boolean rv = false;
        if (order != null && order.getState() != IOrder.State.CLOSED && order.getState() != IOrder.State.CREATED && order.getState() != IOrder.State.CANCELED) {
            rv = true;
        }
        return rv;
    }
    
    private double toPips(Instrument instr, double price) {
        return price / instr.getPipValue();
    }
    
    private String getLabel(Instrument instrument) {
        String label = instrument.name();
        label = label + (counter++);
        label = label.toUpperCase();
        return label;
    }
    
    private void log(String msg) {
        console.getOut().println(msg);
    }
}